<script setup>
import {
  ref,
  watch,
  computed,
  onMounted,
  onBeforeMount,
  onBeforeUnmount,
  provide,
  reactive
} from 'vue'
import {
  getLeavewordListAPI,
  getLeavewordListAuthAPI,
  createLeavewordAPI
} from '@/api/leaveword.js'
import { useCommonStore, useUserStore } from '@/stores'
import { storeToRefs } from 'pinia'
import { message } from '@/components/ZyMessage/index.js'
import { debounce } from '@/utils/common.js'
import { Vue3Lottie } from 'vue3-lottie'
import { useTheme } from '@/hooks/useTheme.js'
import loading_1 from '@/assets/json/loading_1.json'
import ZyHeader from './components/ZyHeader.vue'
import ZyFooter from './components/ZyFooter.vue'
import ZyLabel from './components/ZyLabel.vue'
import LeavewordWall from './components/LeavewordWall.vue'
import ImageWall from './components/ImageWall.vue'
import AddLeaveword from './components/AddLeaveword.vue'
import LeavewordDetail from './components/LeavewordDetail.vue'
import ImageView from './components/ImageView.vue'

const userStore = useUserStore()
const commonStore = useCommonStore()
const { currentWall, isShowHead, isAutoLoad } = storeToRefs(commonStore)
const { user } = storeToRefs(userStore)
const { theme } = useTheme() // 主题切换

// 是否是留言墙
const isLeavewordWall = computed(() => currentWall.value.title === '留言墙')

// 获取留言列表
const loading = ref(false)
const params = reactive({
  page: 1,
  pageSize: 16,
  order: 'time',
  label_id: 0
})
const total = ref(0) // 总数
const totalPage = ref(0) // 总页码
const leavewordList = ref([]) // 留言列表
const isEmpty = ref(false) // 是否显示空状态
const getLeavewordList = async (isShowLoading = true) => {
  let timer = null
  // 是否需要加载效果
  if (isShowLoading) {
    // loading效果延时执行
    timer = setTimeout(() => {
      loading.value = true
    }, 200)
  }
  params.wall_id = currentWall.value.id
  isEmpty.value = false
  try {
    // 判断用户是否登录
    const result = user.value.id
      ? await getLeavewordListAuthAPI(params)
      : await getLeavewordListAPI(params)
    total.value = result.count
    totalPage.value = result.totalPage
    leavewordList.value.push(...result.rows)
  } finally {
    if (timer) clearTimeout(timer)
    loading.value = false
    isLoadMore.value = false
    // 显示空状态
    if (total.value === 0) isEmpty.value = true
  }
}
// 刷新数据
const refreshData = () => {
  cardIndex.value = -1
  params.page = 1
  drawerRef.value?.close()
  leavewordList.value = []
  totalPage.value = 0 // 防止加载更多闪烁
  getLeavewordList()
}

// 触底加载/点击加载更多
const isLoadMore = ref(false) // 是否正在加载中
const onLoadMore = () => {
  if (isLoadMore.value) return
  isLoadMore.value = true
  params.page = params.page + 1
  if (params.page > totalPage.value) return
  getLeavewordList(false)
}

// 抽屉组件
const showBottomBtn = ref(true) // 是否显示底部按钮
const drawerTitle = ref('留言') // 标题
const drawerRef = ref()
// 查看留言详情
const isShowImgView = ref(false) // 是否显示图片预览(照片墙)
const cardIndex = ref(-1) // 当前预览留言卡片下标
const onPreview = (index) => {
  // 1.修改抽屉信息
  drawerTitle.value = '详情'
  showBottomBtn.value = false
  // 2.判断抽屉是否已打开
  if (cardIndex.value === index) {
    return drawerRef.value.close()
  }
  // 3.边界情况(照片墙)
  if (index < 0) {
    cardIndex.value = leavewordList.value.length - 1
  } else if (index === leavewordList.value.length) {
    cardIndex.value = 0
  } else {
    cardIndex.value = index
  }
  // 4.判断是否是留言墙
  if (!isLeavewordWall.value) isShowImgView.value = true
  // 5.打开抽屉
  drawerRef.value.open()
}

// 添加留言
const loadingBtn = ref(false)
const addLeavewordRef = ref()
const onClickAdd = () => {
  if (!user.value.id) return message('请先登录!', 'warning')
  // 重置参数
  drawerTitle.value = '留言'
  showBottomBtn.value = true
  addLeavewordRef.value?.resetParams()
  drawerRef.value.open()
}
const onDrawerClose = () => {
  cardIndex.value = -1
  if (isShowImgView.value) isShowImgView.value = false
}
// 提交数据
const onDrawerSubmit = async () => {
  loadingBtn.value = true
  try {
    // 获取参数
    const createParams = await addLeavewordRef.value.getParams()
    await createLeavewordAPI(createParams)
    refreshData()
    message('留言成功!')
    window.scrollTo(0, 0)
  } finally {
    loadingBtn.value = false
  }
}

// 切换标签
const onChangeLabel = (id) => {
  params.label_id = id
  refreshData()
}
// 排序方式修改
const onChangeSort = (sort) => {
  params.order = sort
  refreshData()
}

// 刷新喜欢状态|喜欢个数
const refreshLike = (id) => {
  const index = leavewordList.value.findIndex((item) => item.id === id)
  const isLike = !leavewordList.value[index].is_like
  leavewordList.value[index].is_like = isLike
  // 改变喜欢个数
  const count = leavewordList.value[index].like_count
  leavewordList.value[index].like_count = isLike ? count + 1 : count - 1
}
// 刷新评论个数
const onRefreshComment = (id) => {
  const index = leavewordList.value.findIndex((item) => item.id === id)
  leavewordList.value[index].comment_count = leavewordList.value[index].comment_count + 1
}

// 切换墙
watch(currentWall, () => {
  params.label_id = 0
  refreshData()
})

// 添加按钮距离底部的距离
const addBtnBottom = ref(20)
const isLeave = ref(false) // 是否离开视口
const setAddBtnBottom = () => {
  // 滚动条高度
  const scrollHeight = document.documentElement.scrollHeight
  // 可视区域高度
  const windowHeight = document.documentElement.clientHeight
  // 滚动条距离顶部的距离
  const scrollPosition = window.scrollY || document.documentElement.scrollTop
  // 滚动条距离底部的距离
  const scrollDistanceToBottom = scrollHeight - scrollPosition - windowHeight
  if (isLeave.value) return (addBtnBottom.value = 20)
  addBtnBottom.value = 185 - scrollDistanceToBottom + 20
}
// 防抖
const debouncedHandler = debounce(setAddBtnBottom, 200)
// 交叉监视器监视底部
const obBottom = new IntersectionObserver(([{ isIntersecting }]) => {
  if (isIntersecting) {
    isLeave.value = false
    // 触底自动加载
    if (isAutoLoad.value && params.page < totalPage.value) {
      onLoadMore()
    }
    window.addEventListener('scroll', debouncedHandler)
  } else {
    isLeave.value = true
    window.removeEventListener('scroll', debouncedHandler)
  }
})

// 交叉监视器监视头部
const obHead = new IntersectionObserver(
  ([{ isIntersecting }]) => {
    isIntersecting ? commonStore.toggleShowHead(true) : commonStore.toggleShowHead(false)
  },
  // top收缩88px
  { rootMargin: '-88px 0px 0px 0px' }
)

// 触底加载/手动加载
const onToggleShowHead = () => {
  commonStore.toggleAutoLoad()
  refreshData()
}

// 向后代组件注入刷新喜欢状态/个数的函数
provide('refreshLike', refreshLike)
// 获取墙的列表
onBeforeMount(async () => {
  await commonStore.getWallList()
})
onMounted(() => {
  obBottom.observe(document.querySelector('.zy-footer'))
  obHead.observe(document.querySelector('.zy-label'))
})
onBeforeUnmount(() => {
  obBottom.disconnect()
  obHead.disconnect()
  window.removeEventListener('scroll', debouncedHandler)
})
</script>

<template>
  <!-- 头部 -->
  <Transition name="down_head">
    <zy-header @refresh="refreshData" v-show="isShowHead" />
  </Transition>
  <!-- 视频背景 -->
  <Transition name="fade_video">
    <video
      class="bg-video"
      v-if="theme === 'light'"
      src="@/assets/video/light.webm"
      autoplay
      muted
      loop
    ></video>
    <video class="bg-video" v-else src="@/assets/video/dark.webm" autoplay muted loop></video>
  </Transition>
  <!-- 内容区域 -->
  <div class="zy-main">
    <p class="title">{{ currentWall.title }}</p>
    <p class="slogan">{{ currentWall.slogan }}</p>
    <!-- 标签 -->
    <zy-label :labels="currentWall.labels" @change="onChangeLabel" @sort="onChangeSort" />
    <!-- 留言墙 -->
    <leaveword-wall
      v-zy-loading="loading"
      v-if="isLeavewordWall"
      :list="leavewordList"
      :is-empty="isEmpty"
      :card-index="cardIndex"
      @preview="onPreview"
    />
    <!-- 照片墙 -->
    <image-wall
      v-else
      v-zy-loading="loading"
      :list="leavewordList"
      :is-empty="isEmpty"
      @preview="onPreview"
    />
    <!-- 加载更多 -->
    <div class="load-more-container" v-if="totalPage >= 1">
      <!-- 是否正在加载中 -->
      <template v-if="!isLoadMore">
        <!-- 当前页码是否小于总页数 -->
        <zy-button
          class="load-more"
          @click="onLoadMore"
          :loading="isLoadMore"
          v-if="params.page < totalPage"
          v-show="!isAutoLoad"
          >点击加载更多...</zy-button
        >
        <div class="not" v-else>- 没有更多了 -</div>
      </template>
      <Vue3Lottie v-else="isLoadMore" :animationData="loading_1" :height="50" :width="50" />
    </div>
  </div>
  <!-- 底部 -->
  <zy-footer />
  <!-- 右侧工具栏 -->
  <div class="tool-container" :style="{ bottom: addBtnBottom + 'px' }">
    <div class="tool-button tool-add" @click="onClickAdd">
      <svg-icon class="tool-icon" icon-name="tianjia" />
    </div>
    <!-- 自动加载或者手动 -->
    <div class="tool-button" @click="onToggleShowHead">
      <svg-icon class="tool-icon" v-if="isAutoLoad" icon-name="manualoading" />
      <svg-icon class="tool-icon" v-else icon-name="autoLoad" />
    </div>
  </div>
  <!-- 弹窗 -->
  <zy-drawer
    ref="drawerRef"
    :title="drawerTitle"
    :show-bottom="showBottomBtn"
    :confirm-loading="loadingBtn"
    :is-delay-close="!isShowImgView"
    @close="onDrawerClose"
    @submit="onDrawerSubmit"
  >
    <!-- 延时通知关闭防止留言详情闪烁 -->
    <add-leaveword v-if="cardIndex === -1" ref="addLeavewordRef" />
    <leaveword-detail v-else :card="leavewordList[cardIndex]" @refresh-comment="onRefreshComment" />
  </zy-drawer>
  <!-- 图片预览 -->
  <image-view
    :is-open="isShowImgView"
    :images="leavewordList"
    :current-index="cardIndex"
    @change="onPreview"
  />
</template>

<style lang="scss" scoped>
.bg-video {
  width: 100vw;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  z-index: -1;
}
.zy-main {
  padding-top: 52px;
  min-height: 700px;
  .title {
    padding-top: 48px;
    padding-bottom: 8px;
    font-size: 56px;
    color: var(--primary-text);
    text-align: center;
    font-weight: 600;
  }
  .slogan {
    color: var(--gray-text-1);
    text-align: center;
  }
}

.load-more-container {
  width: 100%;
  display: flex;
  justify-content: center;
  margin-top: 10px;
  .load-more {
    width: 140px;
    height: 40px;
    border-radius: 24px;
    border: 1px solid var(--primary-text);
    color: var(--primary-text);
  }
  .not {
    color: var(--gray-text-1);
  }
}
.tool-container {
  position: fixed;
  right: 20px;
  transition: var(--tr);
  display: flex;
  flex-direction: column;
  .tool-button {
    width: 45px;
    height: 45px;
    background-color: #fff;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    box-shadow:
      0 2px 8px rgba(28, 31, 35, 0.03),
      0 16px 48px 8px rgba(28, 31, 35, 0.08);
    cursor: pointer;
    .tool-icon {
      color: #1e2023;
      font-size: 20px;
    }
  }
  .tool-add {
    margin-bottom: 10px;
  }
}

/* 进入起点&离开终点 */
.down_head-enter-from,
.down_head-leave-to {
  transform: translateY(-52px);
  opacity: 0;
}
.down_head-enter-active,
.down_head-leave-active {
  transition: all 0.3s;
}
/* 离开起点&进入终点 */
.down_head-enter-to,
.down_head-leave-from {
  transform: translateY(0px);
  opacity: 1;
}

/* 进入起点&离开终点 */
.fade_video-enter-from,
.fade_video-leave-to {
  opacity: 0;
}
.fade_video-enter-active,
.fade_video-leave-active {
  transition: all 0.3s;
}
/* 离开起点&进入终点 */
.fade_video-enter-to,
.fade_video-leave-from {
  opacity: 1;
}
</style>
